/**
 * Copyright (c) 2008, Keisuke Inoue, Syracuse Unviersity
 * All rights reserved.
 *
 */
package edu.syr.iis.web.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hisrc.jscm.codemodel.lang.StringEscapeUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;


import edu.syr.iis.web.model.Assignment;
import edu.syr.iis.web.model.AssignmentManager;
import edu.syr.iis.web.model.DialogueAct;
import edu.syr.iis.web.model.DialogueActDimension;
import edu.syr.iis.web.model.DialogueActDimensionManager;
import edu.syr.iis.web.model.DialogueActLabel;
import edu.syr.iis.web.model.DialogueActLabelManager;
import edu.syr.iis.web.model.Message;
import edu.syr.iis.web.model.User;
import edu.syr.iis.web.model.UserManager;
import edu.syr.iis.web.util.Key;

/**
 * @author kinoue
 *
 */
public class ExportDataController extends AbstractController
{
    UserManager userManager;
    AssignmentManager assignmentManager;
    DialogueActDimensionManager dialogueActDimensionManager;
    DialogueActLabelManager dialogueActLabelManager;    

    static final int FUNCTION = 1; /* not used... just to remind */
    static final int DOMAIN_PART = 2;
    static final int DOMAIN_FULL = 4;
    
    static final int PREV_FUNCTION = 8;
    static final int NEXT_FUNCTION = 16;
    static final int PREV_DOMAIN_PART = 32;
    static final int NEXT_DOMAIN_PART = 64;
    static final int PREV_DOMAIN_FULL = 128;
    static final int NEXT_DOMAIN_FULL = 256;
    /* (non-Javadoc)
     * @see org.springframework.web.servlet.mvc.AbstractController#handleRequestInternal(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request,
	    HttpServletResponse response) throws Exception
	    {
	HashMap<String, Object> model = new HashMap<String, Object>();

	// For the drop-down menu
	List<User> users = userManager.getUsers();

	if (request.getParameter(Key.ANNO1_ID) != null
		&& request.getParameter(Key.ANNO2_ID) != null)
	{
	    User anno1 = userManager.getUser(Integer.parseInt(request.getParameter(Key.ANNO1_ID)));
	    User anno2 = userManager.getUser(Integer.parseInt(request.getParameter(Key.ANNO2_ID)));

	    if (anno1 != null && anno2 != null)
	    {
		// Just for now, set the limit 20 for testing!!
		//
		Collection <Assignment> allAssignments = assignmentManager.getAssignments(1, Assignment.COMPLETED, 20);
		ArrayList <Assignment> assignments = new ArrayList<Assignment>();

		for (Assignment assignment: allAssignments)
		{
		    Collection<Assignment> coAssignments = assignment.getConversation().getAssignments();
		    if (coAssignments.size() > 1)
		    {
			Assignment a = null;
			for (Assignment coAssignment: coAssignments)
			{
			    if (a == null)
				a = coAssignment;
			    else if (coAssignment.getUser().getUserId() == anno1.getUserId())
				a = coAssignment;
			    else if (a.getUser().getUserId() != anno1.getUserId() &&
				    coAssignment.getUser().getUserId() == anno2.getUserId())
				a = coAssignment;    					
			}
			assignments.add(a);
		    } 
		    else 
		    {
			assignments.add(assignment);
		    }
		}
		model.put(Key.ASSIGNMENTS, assignments);   
		model.put("arff", exportData(assignments, FUNCTION, 0));
	    }
	}    		    	
	return new ModelAndView("exportdata", model);
	    }

    public String exportData(Collection<Assignment> assignments, int classOptions, int featureOptions)
    {	

	String nowString =  new Date().toString().replace(' ', '_');
	String content = "%\n";
	String dataContent = "";

	String classLabels = "";
	
	
	DialogueActDimension function = dialogueActDimensionManager.getDialogueActDimension("Function");
	Collection <DialogueActLabel> functionDALabels = dialogueActLabelManager.getDialogueActLabels(function);
	DialogueActDimension domain = dialogueActDimensionManager.getDialogueActDimension("Domain");
	Collection <DialogueActLabel> domainDALabels = dialogueActLabelManager.getDialogueActLabels(domain);
	
	if ((classOptions & FUNCTION) != 0)
	{
	    if ((classOptions & DOMAIN_PART) != 0)
	    {
		    for (DialogueActLabel functionDALabel: functionDALabels) 
		    {
			for (DialogueActLabel domainDALabel: domainDALabels) 
			{
			    if (! classLabels.equals(""))
				classLabels += ", ";
			    classLabels += functionDALabel.getLabel().replace(' ', '_') + domainDALabel.getPartLabel().replace(' ', '_');
			}	    	    
		    }		
	    } 
	    else if ((classOptions & DOMAIN_FULL) != 0)
	    {
		    for (DialogueActLabel functionDALabel: functionDALabels) 
		    {
			for (DialogueActLabel domainDALabel: domainDALabels) 
			{
			    if (! classLabels.equals(""))
				classLabels += ", ";
			    classLabels += functionDALabel.getLabel().replace(' ', '_') + domainDALabel.getLabel().replace(' ', '_');
			}	    	    
		    }		
	    } 
	    else 
	    {
		 for (DialogueActLabel functionDALabel: functionDALabels) 
		 {
		     if (! classLabels.equals(""))
			 classLabels += ", ";
		     classLabels += functionDALabel.getLabel().replace(' ', '_');
		 }
	    }
	} 
	else if ((classOptions & DOMAIN_PART) != 0)
	{
	    for (DialogueActLabel domainDALabel: domainDALabels) 
	    {
		if (! classLabels.equals(""))
		    classLabels += ", ";
		classLabels += domainDALabel.getPartLabel().replace(' ', '_');
	    }	    	    
	} 
	else if ((classOptions & DOMAIN_FULL) != 0)
	{
	    for (DialogueActLabel domainDALabel: domainDALabels) 
	    {
		if (! classLabels.equals(""))
		    classLabels += ", ";
		classLabels += domainDALabel.getLabel().replace(' ', '_');
	    }		
	} 
	
	String functions = "";    // needs to be set !!!	
	String domainsFull = ""; // needs to be set !!
	String domainsPart = ""; // neneds to be set!!

	if ((featureOptions & (PREV_FUNCTION | NEXT_FUNCTION)) != 0)
	{
	    for (DialogueActLabel daLabel: functionDALabels)
	    {
		if (! functions.equals(""))
		    functions += ", ";
		functions += daLabel.getLabel();
	    }	    	    
	}

	if ((featureOptions & (PREV_DOMAIN_FULL | NEXT_DOMAIN_FULL)) != 0)
	{
	    for (DialogueActLabel daLabel: domainDALabels)
	    {
		if (! domainsFull.equals(""))
		    domainsFull += ", ";
		domainsFull += daLabel.getLabel();
	    }	    	    
	}

	if ((featureOptions & (PREV_DOMAIN_PART | NEXT_DOMAIN_PART)) != 0)
	{
	    for (DialogueActLabel daLabel: domainDALabels)
	    {
		if (! domainsPart.equals(""))
		    domainsPart += ", ";
		domainsPart += daLabel.getPartLabel();
	    }	    	    
	}

	int numConversations = assignments.size();
	int numMessages = 0;
	int numDialogueActs = 0;

	
	for (Assignment assignment: assignments)
	{
	    for (Message message: assignment.getConversation().getMessages())
	    {
		numMessages++;
		for (DialogueAct dialogueAct: message.getDialogueActs())
		{
		    if(assignment.getUser().getUserId() == dialogueAct.getUser().getUserId())
		    {
			numDialogueActs++;
			
			String classLabel = "";
			
			if ((classOptions & FUNCTION) > 0)
			    classLabel += dialogueAct.getFunctionLabel();
			if ((classOptions & DOMAIN_PART) > 0) 
			    dataContent += dialogueAct.getPartDomainLabel();
			if ((classOptions & DOMAIN_FULL) > 0)   
			    dataContent += dialogueAct.getDomainLabel();
	
			dataContent += classLabel + ", ";
						
			if ((featureOptions & PREV_FUNCTION) > 0)  
			    dataContent += dialogueAct.getPreviousDialogueActFunctionLabel() + ", ";
			if ((featureOptions & NEXT_FUNCTION) > 0)  
			    dataContent += dialogueAct.getNextDialogueActFunctionLabel() + ", ";
			if ((featureOptions & PREV_DOMAIN_PART) > 0)  
			    dataContent += dialogueAct.getPreviousDialogueActPartDomainLabel() + ", ";
			if ((featureOptions & NEXT_DOMAIN_PART) > 0)   
			    dataContent += dialogueAct.getNextDialogueActPartDomainLabel()  + ", ";
			if ((featureOptions & PREV_DOMAIN_FULL) > 0)  
			    dataContent += dialogueAct.getPreviousDialogueActDomainLabel()  + ", ";
			if ((featureOptions & NEXT_DOMAIN_FULL) > 0)  
			    dataContent += dialogueAct.getNextDialogueActDomainLabel()  + ", ";

			dataContent += assignment.getConversation().getConversationId()  + ", ";
			dataContent += dialogueAct.getMessage().getMessageId()  + ", ";
			dataContent += dialogueAct.getMessage().getSequence()  + ", ";
			dataContent += dialogueAct.getUser().getUserId()  + ", ";
			dataContent += dialogueAct.getMessage().getSpeaker()  + ", ";
			dataContent += "\"" + dialogueAct.getTextSegment().replace('\"', ' ') + "\"\n";
		    }
		}
	    }
	}
	content += "% ARFF file generated by Conversation Annotation Environment \n";
	content += "% " + nowString + "\n"; 
	content += "% Number of conversations: " + numConversations + "\n";
	content += "% Number of messages: " + numMessages + "\n";
	content += "% Number of dialogue acts: " + numDialogueActs + "\n"; 
	content += "% \n";
	content += "@relation conversation_" + nowString + "\n";

	if ((classOptions & FUNCTION) != 0)  
	    content += "@attribute attr_dialogue_act {" + classLabels + "} \n";
	
	if ((featureOptions & PREV_FUNCTION) != 0)  
	    content += "@attribute attr_prev_function {" + functions + ", START1 } \n";

	if ((featureOptions & NEXT_FUNCTION) != 0)  
	    content += "@attribute attr_next_function {" + functions + ", END1 } \n";


	if ((featureOptions & PREV_DOMAIN_PART) != 0)  
	    content += "@attribute attr_prev_domain {"  + domainsPart + ", START1 } \n";

	if ((featureOptions & NEXT_DOMAIN_PART) != 0)  
	    content += "@attribute attr_next_domain {" + domainsPart + ", END1 } \n";


	if ((featureOptions & PREV_DOMAIN_FULL) != 0)  
	    content += "@attribute attr_prev_domain {"  + domainsFull + ", START1 } \n";

	if ((featureOptions & NEXT_DOMAIN_FULL) != 0)   
	    content += "@attribute attr_next_domain {" + domainsFull + ", END1 } \n";

	content += "@attribute attr_conversationId numeric \n";
	content += "@attribute attr_messageId numeric \n";
	content += "@attribute attr_sequence numeric \n";
	content += "@attribute attr_userId numeric \n";
	content += "@attribute attr_speaker {1, 2} \n";

	content += "@attribute attr_text string \n";

	content += "@data \n";  
	content += dataContent;

	return StringEscapeUtils.escapeEcmaScript(content);
	// return content;

    }


    public void setAssignmentManager(AssignmentManager assignmentManager)
    {
	this.assignmentManager = assignmentManager;
    }


    public void setUserManager(UserManager userManager) 
    {
	this.userManager = userManager;
    }

    public void setDialogueActDimensionManager(
	    DialogueActDimensionManager dialogueActDimensionManager)
    {
	this.dialogueActDimensionManager = dialogueActDimensionManager;
    }

    public void setDialogueActLabelManager(DialogueActLabelManager dialogueActLabelManager)
    {
	this.dialogueActLabelManager = dialogueActLabelManager;
    }


}
